//
// Created by admin on 2024/8/18.
//

#include "BandGUI.h"
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <My_BMP280.h>
#include <MAX30105.h>
#include <spo2_algorithm.h>

#include "config.h"
#include "Resource/Fonts.h"
#include "Resource/FreeSans9pt7b.h"
#include "Resource/FreeSansBold18pt7b.h"

#include "Control.h"
#include "Senior.h"

extern Control control;
extern Senior senior;
extern BMP280 bmp;

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
MAX30105 particleSensor;

uint32_t irBuffer[100]; //infrared LED sensor data
uint32_t redBuffer[100];  //red LED sensor data

int32_t bufferLength; //data length
int32_t spo2; //SPO2 value
int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
int32_t heartRate; //heart rate value
int8_t validHeartRate; //indicator to show if the heart rate calculation is valid


const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
int beatAvg;


void drawChinese(uint16_t x,uint16_t y,char* ChineseStr){
    //声明已有字库的数组并与name里面的对照
    char chinese[] = "次分度月日手电响铃海拔";
//    Serial.print("Lenght");
//    Serial.println(strlen(ChineseStr));
    for(int i = 0;i<strlen(ChineseStr);i+=3){
        for(int j=0;j<strlen(chinese);j+=3){
            if(ChineseStr[i]==chinese[j]&&ChineseStr[i+1]==chinese[j+1]){
//                Serial.println(j/3);
                display.drawBitmap(x+i/3*14,y,Chinese14px[j/3],14,14,SSD1306_WHITE);
                break;
            }
        }
    }
}

void drawNummber(int x,int y,int nummber,bool isBig){
    char num = nummber/100,start_x=x;
    if(num!=0){
        display.drawBitmap(start_x,y,Number30px[nummber/100],19,42,SSD1306_WHITE);
        start_x+=20;
    }
    num = nummber%100;
    display.drawBitmap(start_x,y,Number30px[num/10],19,42,SSD1306_WHITE);
    display.drawBitmap(start_x+20,y,Number30px[num%10],19,42,SSD1306_WHITE);
    if(isBig){
        display.drawBitmap(start_x+40,y,Number30px[10],19,42,SSD1306_WHITE);
    }
}

void drawBattery(int x,int y){
    int width = 22,height = 12;
    display.drawRoundRect(x, y, width, height, 2, SSD1306_WHITE);
    int vol = analogReadMilliVolts(BAT_PIN)*2;
    vol = constrain(vol, 3650, 4200);
    width = map(vol, 3650, 4200, 4, 22);
    display.fillRoundRect(x,y,width, height, 2, SSD1306_WHITE);
}

void BandGUI::init() {
    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
    if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
        Serial.println(F("SSD1306 allocation failed"));
    }
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
    {
        Serial.println(F("MAX30105 was not found. Please check wiring/power."));
    }

//    Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
//    while (Serial.available() == 0) ; //wait until user presses a key
//    Serial.read();

    byte ledBrightness = 60; //Options: 0=Off to 255=50mA
    byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
    byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
    byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
    int pulseWidth = 411; //Options: 69, 118, 215, 411
    int adcRange = 4096; //Options: 2048, 4096, 8192, 16384

    particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
    particleSensor.shutDown();
    bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps
}

/*
 * 主窗口
 * 显示温度、湿度、皮肤温度、时间、日期、电池电量
 */
void BandGUI::MainWin() {


//    // Draw a single pixel in white
//    display.drawPixel(10, 10, SSD1306_WHITE);
//    delay(2000);
    display.clearDisplay();

    display.setFont(&FreeSans9pt7b);
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);

    //温湿度显示
    display.drawBitmap(0,0,Temperature, 10, 15, SSD1306_WHITE);
    display.setCursor(11, 12);
    display.println(String(senior.getTemperature(), 1));
    drawChinese(48, 0, "度");

    display.drawBitmap(0,64-15,Humidity, 16, 16, SSD1306_WHITE);
    display.setCursor(15, 63);
    display.print(String(senior.getHumidity(), 1)+"^");

    //皮肤温度显示
    begin_x = 66;
    display.drawBitmap(begin_x,0,SKinTemperature, 10, 15, SSD1306_WHITE);
    display.setCursor(begin_x+11, 12);
    display.println(String(senior.getSkinTemperature(), 1));
    drawChinese(begin_x+46, 0, "度");

    //时间显示
    begin_x= 12;
    begin_y = 11;
    drawNummber(begin_x,begin_y,timeStruct.hours, true);
    drawNummber(begin_x+50,begin_y,timeStruct.minutes, false);

    display.setFont(&FreeSans9pt7b);
    display.setTextSize(1);
    display.setCursor(begin_x+50+38, 44);
    display.print(":");
    display.print(String(timeStruct.seconds/10));
    display.println(String(timeStruct.seconds%10));

    //日期显示
    begin_x = 64;
    begin_y = 63;
    display.setCursor(begin_x, begin_y);
    display.print(dateStruct.month/10);
    display.print(dateStruct.month%10);
    drawChinese(begin_x+20, begin_y-12, "月");
    display.setCursor(begin_x+32, begin_y);
    display.print(dateStruct.date/10);
    display.print(dateStruct.date%10);
    drawChinese(begin_x+50, begin_y-12, "日");

    //电池电量
    begin_x = 102;
    begin_y = 17;
    drawBattery(begin_x, begin_y);

    display.display();
}

/*
 * 心率界面需要先启动 MAX30102 传感器并且初始化
 */
void BandGUI::BPM_Init() {
    display.clearDisplay();
    display.display();
    display.setFont(&FreeSans9pt7b);
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(1,15);
    display.println("Senior Begin");
    display.print("Wait For 4 Second ");
    display.display();
    particleSensor.wakeUp();
    //read the first 100 samples, and determine the signal range
    for (byte i = 0 ; i < bufferLength ; i++)
    {
        while (particleSensor.available() == false) //do we have new data?
            particleSensor.check(); //Check the sensor for new data

        redBuffer[i] = particleSensor.getRed();
        irBuffer[i] = particleSensor.getIR();
        particleSensor.nextSample(); //We're finished with this sample so move to next sample

        Serial.print(F("red="));
        Serial.print(redBuffer[i], DEC);
        Serial.print(F(", ir="));
        Serial.println(irBuffer[i], DEC);
    }

    //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
    display.println("Done!");
    display.display();
    delay(1000);
    display.clearDisplay();
}

//显示心率界面
void BandGUI::BPM_With_SPO2() {

    display.clearDisplay();
    //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
    for (byte i = 25; i < 100; i++)
    {
        redBuffer[i - 25] = redBuffer[i];
        irBuffer[i - 25] = irBuffer[i];
    }

    //take 25 sets of samples before calculating the heart rate.
    for (byte i = 75; i < 100; i++)
    {
        while (particleSensor.available() == false) //do we have new data?
            particleSensor.check(); //Check the sensor for new data

        redBuffer[i] = particleSensor.getRed();
        irBuffer[i] = particleSensor.getIR();
        particleSensor.nextSample(); //We're finished with this sample so move to next sample


        //send samples and calculation result to terminal program through UART
        Serial.print(F("red="));
        Serial.print(redBuffer[i], DEC);
        Serial.print(F(", ir="));
        Serial.print(irBuffer[i], DEC);


        Serial.print(F(", HR="));
        Serial.print(heartRate, DEC);

        Serial.print(", Avg BPM=");
        Serial.print(beatAvg);

        Serial.print(F(", HRvalid="));
        Serial.print(validHeartRate, DEC);

        Serial.print(F(", SPO2="));
        Serial.print(spo2, DEC);

        Serial.print(F(", SPO2Valid="));
        Serial.println(validSPO2, DEC);
    }

    //After gathering 25 new samples recalculate HR and SP02
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);


    display.drawBitmap(0,1,HeartRate,30,30,SSD1306_WHITE);

    display.drawBitmap(0,34,SPO2,30,30,SSD1306_WHITE);

    display.drawBitmap(80,31,SKinTemperature,10,15,SSD1306_WHITE);
    display.setFont(&FreeSans9pt7b);
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(90,44);
    display.print("30.2");




    begin_y = 14;
    heartRate = validHeartRate?heartRate:0;
    spo2 = validSPO2?spo2:0;
    begin_x = heartRate>=100?90:70;
    display.setFont(&FreeSansBold18pt7b);
    display.setCursor(32,26);
    display.print(heartRate);
    display.setCursor(32,60);
    display.print(spo2);
    display.setFont(&FreeSans9pt7b);
    display.print("%");
    drawChinese(begin_x,begin_y,"次分");
    display.display();

    if (heartRate < 255 && heartRate > 20)
    {
        rates[rateSpot++] = (byte)heartRate; //Store this reading in the array
        rateSpot %= RATE_SIZE; //Wrap variable

        //Take average of readings
        beatAvg = 0;
        for (byte x = 0 ; x < RATE_SIZE ; x++)
            beatAvg += rates[x];
        beatAvg /= RATE_SIZE;
    }

}

//关闭心率传感器
void BandGUI::BPM_ShutDown() {
    particleSensor.shutDown();
    display.clearDisplay();
    control.setRGB(0,50,50,50);
    control.setRGB(1,50,50,50);
    delay(100);
    control.CloseRGB();
}

/*
 * 压力界面
 * 显示BMP280信息和日期
 */
void BandGUI::MPressure() {
    display.clearDisplay();
    display.drawBitmap(0,1,Pressure,30,30,SSD1306_WHITE);

    display.setFont(&FreeSans9pt7b);
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    begin_x = 32;
    begin_y = 14;
    display.setCursor(begin_x, begin_y);
    display.print(bmp.readTemperature());
    display.println("C");
    begin_y += 16;
    display.setCursor(begin_x, begin_y);
    display.print(String(bmp.readPressure()/1000,3));
    display.print("Kpa");

    begin_y += 16;
    display.setCursor(begin_x, begin_y);
    display.print(bmp.readAltitude());
    display.print("m");
    drawChinese(1,begin_y-14,"海拔");

    //日期显示
    begin_x = 0;
    begin_y = 61;
    display.setCursor(begin_x, begin_y);
    String timestr = "";
    timestr += String(dateStruct.month/10) + String(dateStruct.month%10);
    timestr += "/";
    timestr += String(dateStruct.date/10) + String(dateStruct.date%10);
    timestr += "  ";
    timestr += String(timeStruct.hours/10) + String(timeStruct.hours%10);
    timestr += ":";
    timestr += String(timeStruct.minutes/10) + String(timeStruct.minutes%10);
    timestr += ":";
    timestr += String(timeStruct.seconds/10) + String(timeStruct.seconds%10);
    display.print(timestr);
    display.display();
}

//设置灯光
void BandGUI::Light_Setting() {
    display.clearDisplay();
    display.display();
}